'use strict';
/** 登录服务器组队队列 */
global.LIST || (global.LIST = []);
/** 游戏服务器队列信息缓存 */
global.MAPLIST || (global.MAPLIST = {});

/** 躲猫猫游戏的消息 */
module.exports.run = function(d,s){
    const bs = require("../module/base"), mapc = require("../config/map"), bag = require("./bag"), task = require("./task");
    switch(d[1]){
        case 1:{ //登录服务器进入队列
            let mid = (d[2] && d[2].mapid) || 0;
            if(!mapc[mid]) return bs.sendE(s, 104);
            if("mapid" in s.U) return bs.sendE(s, 101);
            /**
             * LIST 缓存对应地图的等待队列
             * 每个用户是一个对象
             *  uid 对应用户的id
             *  t 最后进入队列的时间
             */
            global.LIST[mid] || (global.LIST[mid] = []);
            global.LIST[mid].push({uid:s.U.uid,t:Date.now()});
            s.U.mapid = mid;
            bs.send(s,d);
            if(global.LIST[mid].length >= mapc[mid].UserNum){ //队列满了可以分配地图了
                OnTime();
            }
            break;
        }case 2:{ //人物移动
            if(d[2].length != 3) return;
            let map = MAPLIST[s.U.mk];
            let sd = `[9,102,[${s.U.uid},${d[2][0]},${d[2][1]},${d[2][2]}]]`;
            for(let k in map.u){
                if(map.u[k].on && k != s.U.uid){
                    bs.sendUser(k, sd);
                }
            }
            let mu = map.u[s.U.uid];
            mu.lx = mu.x, mu.ly = mu.y, mu.lz = mu.z;
            mu.x = d[2][0], mu.y = d[2][1], mu.z = d[2][2];
            break;
        }case 3:{ //攻击物品
            if(d.length != 3) return;
            let map = MAPLIST[s.U.mk];
            if(d[2] in map.u && map.u[d[2]].PH > 0){
                let dis = Math.sqrt((map.u[s.U.uid].x-map.u[d[2]].x)*(map.u[s.U.uid].x-map.u[d[2]].x)+(map.u[s.U.uid].z-map.u[d[2]].z)*(map.u[s.U.uid].z-map.u[d[2]].z));
                if(dis < 5){ //判断距离
                    map.u[d[2]].PH--;
                    let sd = `[9,103,[${d[2]},${map.u[d[2]].PH}]]`;
                    for(let k in map.u){
                        if(map.u[k].on) bs.sendUser(k, sd);
                    }
                    if(map.u[s.U.uid].PH < 5){
                        map.u[s.U.uid].PH++;
                        sd = `[9,103,[${s.U.uid},${map.u[s.U.uid].PH}]]`;
                        for(let k in map.u){
                            if(map.u[k].on) bs.sendUser(k, sd);
                        }
                    } 
                    //判断游戏是否结束
                    return checkGame();
                }else{
                    LOG.error("dis", dis);
                }
            }
            //console.log(map.u[d[2]].PH);
            //攻击失败
            if(map.u[s.U.uid].PH > 0){
                map.u[s.U.uid].PH--;
                let sd = `[9,103,[${s.U.uid},${map.u[s.U.uid].PH}]]`;
                for(let k in map.u){
                    if(map.u[k].on) bs.sendUser(k, sd);
                }
            }
            checkGame();
            break;
        }case 9:{ //游戏服务登录 进入地图
            if(!bs.checkParam(["k","uid"], d)) return;
            if(d[2].uid in USERMAP){
                bs.sendE(s, 2);
                return;
            } 
            function _ent(){
                //console.log(MAPLIST);
                let map = MAPLIST[d[2].k];
                if(d[2].uid in map.u){
                    map.u[d[2].uid].on = 1;
                    s.U = {uid:d[2].uid,mk:d[2].k};
                    USERMAP[s.U.uid] = s;
                    d[2] = {t:map.u[s.U.uid].t,rid:map.u[d[2].uid].rid};
                    if("x" in map.u[s.U.uid]) d[2].x = map.u[s.U.uid].x, d[2].y = map.u[s.U.uid].y, d[2].z = map.u[s.U.uid].z;
                    bs.send(s, d);
                    /** 给所有进入的玩家发进入 */
                    for(let k in map.u){
                        if(map.u[k].on && k != s.U.uid){
                            let up = [9,0,{"uid":s.U.uid,"rid":map.u[s.U.uid].rid}];
                            if("x" in map.u[s.U.uid]) up[2].x = map.u[s.U.uid].x, up[2].y = map.u[s.U.uid].y, up[2].z = map.u[s.U.uid].z;
                            if("lx" in map.u[s.U.uid]) up[2].lx = map.u[s.U.uid].lx, up[2].ly = map.u[s.U.uid].ly, up[2].lz = map.u[s.U.uid].lz;
                            bs.sendUser(k, up);
                            up = [9,0,{"uid":k,"rid":map.u[k].rid}];
                            if("x" in map.u[k]) up[2].x = map.u[k].x, up[2].y = map.u[k].y, up[2].z = map.u[k].z;
                            if("lx" in map.u[k]) up[2].lx = map.u[k].lx, up[2].ly = map.u[k].ly, up[2].lz = map.u[k].lz;
                            bs.send(s, up);
                        }
                    }
                }else bs.sendE(s, 103);
                console.log("end", JSON.stringify(MAPLIST));
            }
            if(d[2].k in MAPLIST) _ent();
            else{
                bs.RS(0).GET("MP" + d[2].k, (err,rep)=>{
                    if(err) return;
                    if(!rep){
                        bs.sendE(s, 102);
                        return;
                    }
                    if(!(d[2].k in MAPLIST)) MAPLIST[d[2].k] = JSON.parse(rep);
                    _ent();
                });
            }
            break;
        }case 44:{ //强制退出地图
            bs.RS(0).HDEL("USER", s.U.uid);
            break;
        }default:{
            LOG.error("not msg", d);
        }
    }
}

/** 匹配捉迷藏队列 用定时器是为了添加机器人 */
function OnTime(){
    const server = require("../config/Server"), mapc = require("../config/map.json");
    let bs = require("../module/base");
    for(let mid=0;mid<mapc.length;mid++){
        global.LIST[mid] || (global.LIST[mid] = []);//console.log(mid, mapc);
        if(mapc[mid].UserNum > LIST[mid].length) continue;
        /** md 地图缓存数据 
         *      mapid 地图唯一id
         *      url 服务器地址
         *      end 1游戏结束
         *      u 用户缓存的数据 uid作为key
         *          rid 角色模型id
         *          t   用户类型 0找 1藏
         *          on  当前是否在线 在地图服务器上才有效
         *          PH  血量0时已经失败了 找的人有血量5 藏的人血量1
         *          x,y,z 当前坐标
         *          lx,ly,lz 上一次的坐标位置
         */
        let mkey = bs.MD5(Date.now().toString()), md = {mapid:mid,url:"",u:{},ru:{}}, ul = [], rdc = ["USER"];
        let f = mapc[mid].find, fx = mapc[mid].UserNum - f;
        for(let i=0;i<mapc[mid].UserNum;i++){ //分配用户
            let uid = LIST[mid][i].uid;
            ul.push(uid);
            md.u[uid] = {};
            if(Math.random()*100 < 50) md.u[uid].t = 0; //找
            else md.u[uid].t = 1; //藏
            if(md.u[uid].t == 0 && f == 0) md.u[uid].t = 1;
            else if(md.u[uid].t == 1 && fx == 0) md.u[uid].t = 0;
            if(md.u[uid].t == 1){ //随机藏的物品
                md.u[uid].rid = mapc[mid].roleList[(Math.random()*mapc[mid].roleList.length)|0];
                md.u[uid].PH = 1;
                fx--;
            }else{
                md.u[uid].rid = 0;
                md.u[uid].PH = 5;
                f--;
            }
            rdc.push(uid, mkey);
            USERMAP[uid] && USERMAP[uid].U && delete USERMAP[uid].U.mapid;
        }
        for(let i=0;i<mapc[mid].randRole.num;i++){ //分配随机生成的物品

        }
        serverIndex++;
        if(serverIndex >= server.length) serverIndex = 0;
        md.url = server[serverIndex];
        bs.RS(0).SETNX("MP"+mkey, JSON.stringify(md), (err, rep)=>{
            if(err) return;
            if(rep == 1){
                LIST[mid] = LIST[mid].slice(mapc[mid].UserNum);
                bs.sendUser(ul, `[1,99,{"url":"${md.url}","mkey":"${mkey}","mapid":${md.mapid}}]`);
                bs.RS(0).HMSET(rdc)
            }
        });
    }
}

let tv = setInterval(OnTime, 3000);
exports.destroy = function(){
    clearInterval(tv);
}

/** 检查游戏是否结束 */
function checkGame(){
    const bs = require("../module/base");
    for(let mk in MAPLIST){
        let map = MAPLIST[mk];
        if(map.end) continue;
        let ft = 0,ct = 0;
        for(let k in map.u){
            if(map.u[k].t == 1 && map.u[k].PH > 0) ct = 1;
            if(map.u[k].t == 0 && map.u[k].PH > 0) ft = 1;
        }
        if(ft && ct) continue;
        let sd = `[9,99]`;
        for(let k in map.u){
            if(map.u[k].on) bs.sendUser(k, sd);
        }
        map.end = 1;
    }
}


/** 登录事件 */
module.exports.login = function(s){
    const bs = require("../module/base"), bag = require("./bag");
    //获取用户属性
    if(!s.U.game){
        s.U.game = {"lv":1,"boxnum":1};
    } 
    bag.run([3,1], s);
    bs.send(s, [2,8,s.U.game]);

    //检查是否有正在玩的对局(躲猫猫游戏)
    bs.RS(0).HGET("USER", s.U.uid, (e,rep)=>{
        if(e) return;
        if(rep){
            bs.RS(0).GET("MP" + rep, (err,mp)=>{
                if(err) return;
                if(!mp) return;
                let md = JSON.parse(mp);
                bs.send(s, `[1,99,{"url":"${md.url}","mkey":"${rep}","mapid":${md.mapid}}]`);
            });
        }
    });
}

/** 游戏退出 */
module.exports.loginout = function(s){
    for(let i=0;LIST[s.U.mapid] && i<LIST[s.U.mapid].length;i++){ //清理队列
        if(LIST[s.U.mapid][i].uid == s.U.uid) LIST[s.U.mapid].splice(i,1);
    }
    //躲猫猫游戏处理
    if(s.U.mk && s.U.mk in MAPLIST){
        let map = MAPLIST[s.U.mk];
        map.u[s.U.uid].on = 0;
        //是否所有人都断线了 都下线清理地图
        let dOn = ['USER'];
        let sd = `[9,98,${s.U.uid}]`, isOn = false;
        for(let k in map.u){
            if(map.u[k].on){ //通知下线
                bs.sendUser(k, sd);
                isOn = true;
                continue;
            }
            dOn.push(k);
        }
        if(isOn) return;
        delete MAPLIST[s.U.mk];
        bs.RS(0).HDEL(dOn);
        bs.RS(0).DEL("MP"+s.U.mk);
    }
}

/** 获得道具 */
module.exports.getitem = function(s, it){
    
}